﻿
#If Not (PocketPC OrElse Smartphone) Then

Imports System.Threading
Imports System.Net
Imports std
Imports httpContext

Public Class httpServer2
    Inherits httpServer
    Public Shadows Event reject(ByVal context As httpContext)
    Public Shadows Event receive(ByVal context As httpContext)
    Private Shared HTTPSERVER2_PROCESS_TIMEMS As Int64

    Protected contextpool As contextPoolDefinition = Nothing

    <ThreadStatic()> Public Shared _currentContext As httpContext = Nothing

    Shared Sub New()
        HTTPSERVER2_PROCESS_TIMEMS = counter.registerAverageAndLastAverage("HTTPSERVER2_PROCESS_TIMEMS")
    End Sub

    Public Shared Function currentContext() As httpContext
        assert(Not _currentContext Is Nothing, "httpServer2._currentContext is nothing.")
        Return _currentContext
    End Function

    Public Sub New(Optional ByVal para As parameterDefinition = Nothing)
        contextpool = New contextPoolDefinition(para)
    End Sub

    Private Delegate Sub caller(ByVal context As httpContext, ByVal rejectIssues As Byte)

    Private Sub receiveCaller(ByVal context As httpContext, ByVal __NOT_IN_USE__ As Byte)
        RaiseEvent receive(context)
    End Sub

    Private Sub rejectCaller(ByVal context As httpContext, ByVal rejectIssues As Byte)
        context.setRejectIssues(rejectIssues)
        RaiseEvent reject(context)
    End Sub

    Private Sub eventhandle(ByVal listenerContext As HttpListenerContext, ByVal caller As caller, _
                            Optional ByVal rejectIssues As Byte = 0)
        assert(Not listenerContext Is Nothing, "listenerContext is nothing when start handle")
        assert(Not caller Is Nothing, "caller is nothing when start handle")
        Dim context As httpContext = Nothing
        Dim index As Int64
        If Not contextpool.getfree(index, context) Then
            raiseError("cannot get free httpContext instance from contextpool, ignore request." _
                       , errorHandle.errorType.warning)
            Try
                listenerContext.Response.StatusCode = Net.HttpStatusCode.ServiceUnavailable
                listenerContext.Response.StatusDescription = "SERVICE_UNAVAILABLE"
            Catch ex As Exception
                raiseError("failed to set unavailable status. " + ex.Message, errorHandle.errorType.warning)
            End Try
            Try
                closestream(listenerContext.Request.InputStream)
                closestream(listenerContext.Response.OutputStream)
                listenerContext.Response.Close()
            Catch ex As Exception
                raiseError("failed to close response & request. " + ex.Message, errorHandle.errorType.warning)
            End Try
        Else
            Dim startticks As Int64 = 0
            startticks = Now.Ticks()
            _currentContext = context
            context.listenerContext() = listenerContext
            Try
                caller(context, rejectIssues)
            Catch ex As ThreadAbortException
                raiseError("thread abort.", errorHandle.errorType.warning)
            Catch ex As Exception
                raiseError("caught unhandled exception in eventhandle, " + context.url().full + ", " _
                           + ex.Message + ", " + ex.StackTrace, errorHandle.errorType.critical)
            End Try
            counter.increase(HTTPSERVER2_PROCESS_TIMEMS, ticksToMilliseconds(Now.Ticks() - startticks))
            If Not context Is Nothing Then
                context.close()
            End If
            contextpool.release(index)
        End If
    End Sub

    Private Sub httpServer2_reject(ByVal listenerContext As HttpListenerContext, _
                                   ByVal rejectIssues As Byte) Handles MyBase.reject
        eventhandle(listenerContext, AddressOf rejectCaller, rejectIssues)
    End Sub

    Private Sub httpServer2_receive(ByVal listenerContext As HttpListenerContext) Handles MyBase.receive
        eventhandle(listenerContext, AddressOf receiveCaller)
    End Sub
End Class

#End If
